#include "platform.h"

float  DA10[11]  = {0.529,0.623,0.717,0.812,0.906,1.000,1.094,1.187,1.281,1.373,1.466};
float Coef_fix[11]={0.946,0.963,0.976,0.985,0.993,1.000,1.005,1.011,1.015,1.019,1.023};


uint8_t CAP_AFE_Transmit(uint8_t DeviceAddr, uint8_t reg, uint8_t Data);
uint8_t CAP_AFE_Receive(uint8_t DeviceAddr, uint8_t reg,uint8_t *pData);
//GPIOI2C_BusStateDef GPIOI2C_Bus_Init();
/*******************************************************************
  * @brief  Find frequency division values.
  * @param  Data:Register Value.
  * @param  div:division factor.
  * @retval None.
 ******************************************************************/
static void Get_FinDiv(u8 Data ,u16* div)
{
	switch(Data>>4)
	{
		case 0:
			*div=1;
		break;
		case 1:
			*div=2;
		break;
		case 2:
			*div=4;
		break;
		case 3:
			*div=8;
		break;
		case 4:
			*div=16;
		break;
		case 5:
			*div=32;
		break;
		case 6:
			*div=64;
		break;
		case 7:
			*div=128;
		break;
		default :
			*div = 256;
		break;
	}
}	
	
/*******************************************************************
  * @brief  Capacitance correction.
  * @param  Cap_Structure.
  * @retval none.
 ******************************************************************/	
void DA1_DA0(CAP_AFE* Cap_Structure)
{
	float k,b,DATA;
	DATA = (Cap_Structure->R_F/Cap_Structure->M_F);
	for(int i=0;i<11;i++)
	{
		if(DATA<DA10[0])DATA=DA10[0];
		else if(DATA>DA10[10])DATA=DA10[10];
	

		if(DATA<DA10[i])
		{
			k=(Coef_fix[i]-Coef_fix[i-1])/(DA10[i]-DA10[i-1]);
			b=Coef_fix[i]-k*DA10[i];
			Cap_Structure->coef=k*DATA+b;
			break;
		}
		else if(DATA==DA10[i])
		{
			Cap_Structure->coef=Coef_fix[i];
			break;
		}
	}

}



/*******************************************************************
  * @brief  initialization Registers.
  * @param  Cap_Structure.
  * @retval None.
 ******************************************************************/
void Registers_Init(CAP_AFE* Cap_Structure)
{
	//Send soft reset request
	CAP_AFE_Transmit(I2C_ADDR,MC_RESET,RESET_CMD);
	Delay_ms(30);
	
	u8	cfg;
	CAP_AFE_Receive(I2C_ADDR,CFG,&cfg);		
	cfg &=~(0x03) ;
	cfg |= OS_SD_Stop_Trans;	
	
	
	if(Cap_Structure->clk == Ex_CLK)
	{
		cfg &=~(0x80) ;
		cfg |= REF_SEL_Ex_CLK;	
		CAP_AFE_Transmit(I2C_ADDR,CFG,cfg);//CAP AFE stop measurement
		Delay_ms(20);
		
		//Configuration establishment time 100us
		CAP_AFE_Transmit(I2C_ADDR,SCNT,0x4b);
	}
	else
	{
		cfg &=~(0x80) ;
		cfg |= REF_SEL_In_CLK;	
		CAP_AFE_Transmit(I2C_ADDR,CFG,cfg);//CAP AFE stop measurement
		Delay_ms(20);
		////Configuration establishment time 100us
		CAP_AFE_Transmit(I2C_ADDR,SCNT,0x0f);

	}	
	//Configure measurement channels
	CAP_AFE_Transmit(I2C_ADDR,CHX_EN,CH0_ENABLE|CH1_ENABLE);
	
	//Configure driving currentI_DRIVE
  CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,Cap_Structure->I_DRIVE);
//	#if	 DRIVE_I_200UA
//		
//	#elif DRIVE_I_400UA
//		CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,DRIVE_I_400UA);
//	#elif DRIVE_I_800UA
//		CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,DRIVE_I_800UA);		
//	#elif DRIVE_I_1600UA
//		CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,DRIVE_I_1600UA);		
//	#elif DRIVE_I_2400UA
//		CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,DRIVE_I_2400UA);
//	#elif	DRIVE_I_3200UA
//		CAP_AFE_Transmit(I2C_ADDR,DRIVE_I,DRIVE_I_3200UA);		
//	#endif
	
	//Configure sampling frequency division coefficient
	CAP_AFE_Transmit(I2C_ADDR,FREF_DIV,Cap_Structure->FREF_DIV);	
	//    Ƶ ʷ Ƶ
	CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,Cap_Structure->FIN_DIV);
//	#if	 CH0_FIN_DIV_0	
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_0);
//	#elif	CH0_FIN_DIV_2
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_2);
//	#elif	CH0_FIN_DIV_4
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_4);
//	#elif	CH0_FIN_DIV_8
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_8);
//	#elif	CH0_FIN_DIV_16
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_16);
//	#elif	CH0_FIN_DIV_32
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_32);
//	#elif	CH0_FIN_DIV_64
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_64);	
//	#elif	CH0_FIN_DIV_128
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_128);
//	#elif	CH0_FIN_DIV_256
//		CAP_AFE_Transmit(I2C_ADDR,FIN_DIV,CH0_FIN_DIV_256);
//#endif		
	//Configure conversion time
	CAP_AFE_Transmit(I2C_ADDR,RCNT_MSB,RCNT_D>>8);
	CAP_AFE_Transmit(I2C_ADDR,RCNT_LSB,RCNT_D&0XFF);
	
}

/*******************************************************************
  * @brief  Start Measurement.
  * @note  	none
  * @param  Cap_Structure.
  * @retval None.
 ******************************************************************/
u32 wait_time;
void Single_Measure(CAP_AFE* Cap_Structure)
{
	u8 sta=0,FIN0_DIV,scnt,error_n=0;
	u8 data_msb,data_lsb,cfg,RCNTM,RCNTL;
	u32 timeout;
	float f0_ave=0,f1_ave=0;
	u16 REV_RCNT,div;
	u8 get_ch;
	float f0_array[AVG_COUNT], f1_array[AVG_COUNT];

	//Read register clear flag bit
	CAP_AFE_Receive(I2C_ADDR,DATA_CH0_MSB,&data_msb);
	CAP_AFE_Receive(I2C_ADDR,DATA_CH0_LSB,&data_lsb);
	CAP_AFE_Receive(I2C_ADDR,DATA_CH1_MSB,&data_msb);
	CAP_AFE_Receive(I2C_ADDR,DATA_CH1_LSB,&data_lsb);
	
	CAP_AFE_Receive(I2C_ADDR,SCNT,&scnt);
	
	CAP_AFE_Receive(I2C_ADDR,CHX_EN,&get_ch);	
	//Get RCNT
	CAP_AFE_Receive(I2C_ADDR,RCNT_MSB,&RCNTM);	
	CAP_AFE_Receive(I2C_ADDR,RCNT_LSB,&RCNTL);
	REV_RCNT=RCNTM<<8|RCNTL;
	
	//Calculate conversion time
	if((get_ch>>6)<3)wait_time =(int)((((float)scnt*16+(float)REV_RCNT+4)/(Cap_Structure->clkfre*1000))+1);
	else wait_time =(int)((((float)scnt*16+(float)REV_RCNT+4)/(Cap_Structure->clkfre*1000))*2+1);
	
	CAP_AFE_Receive(I2C_ADDR,FIN_DIV,&FIN0_DIV); 
	Get_FinDiv(FIN0_DIV,&div);	//Get frequency division coefficient

	f0_ave = 0;
	f1_ave = 0;
	CAP_AFE_Receive(I2C_ADDR,CFG,&cfg);		
	cfg &=~(0x03) ;
	cfg |= OS_SD_Single_Trans;	
	for(u8 k = 0;k<cap_structure.avg;k++)
	{
		timeout =20;
		CAP_AFE_Transmit(I2C_ADDR,CFG,cfg);
		Delay_ms(wait_time);	//Waiting for measurement completion
		CAP_AFE_Receive(I2C_ADDR,STATUS,&sta);
		if(!((sta&0x30)==(get_ch>>6)<<4))	//Detection conversion completion flag
		{
			__measure3: 
			CAP_AFE_Receive(I2C_ADDR,STATUS,&sta);
			timeout--;
			if(!((sta&0x30)==(get_ch>>6)<<4) && timeout>0) goto __measure3;	
		}
		if(timeout>0)
		{
			CAP_AFE_Receive(I2C_ADDR,DATA_CH0_MSB,&data_msb);//Get channel 0 data
			CAP_AFE_Receive(I2C_ADDR,DATA_CH0_LSB,&data_lsb);
			//*F0
			// f0_ave += ((data_msb<<8|data_lsb));
			f0_array[k] = (data_msb<<8|data_lsb); // 通道0	
		
			CAP_AFE_Receive(I2C_ADDR,DATA_CH1_MSB,&data_msb);//Get channel l data
			CAP_AFE_Receive(I2C_ADDR,DATA_CH1_LSB,&data_lsb);

			//*F1 
			// f1_ave += ((data_msb<<8|data_lsb));
			f1_array[k] = (data_msb<<8|data_lsb); // 通道1
		}
		else error_n++; 
	}
	//从大到小排序
	sort(f0_array, cap_structure.avg-error_n);
	sort(f1_array, cap_structure.avg-error_n);
	uint8_t realAvg = cap_structure.avg-error_n;
	
	if(cap_structure.Reference_channel == CH0)	
	{
		Cap_Structure->count_ch0 = f0_array[realAvg/2];
		Cap_Structure->count_ch1 = f1_array[realAvg/2];
		// Cap_Structure->count_ch0 = f0_ave/(cap_structure.avg-error_n);
		// Cap_Structure->count_ch1 = f1_ave/(cap_structure.avg-error_n);
	}
	else if(cap_structure.Reference_channel == CH1)
	{
		Cap_Structure->count_ch0 = f1_array[realAvg/2];
		Cap_Structure->count_ch1 = f0_array[realAvg/2];
		// Cap_Structure->count_ch0 = f1_ave/(cap_structure.avg-error_n);
		// Cap_Structure->count_ch1 = f0_ave/(cap_structure.avg-error_n);
	}

	Cap_Structure->R_F = (float)(Cap_Structure->count_ch0)*div*Cap_Structure->clkfre/(float)REV_RCNT;	//Calculate channel 0 frequency
	Cap_Structure->M_F = (float)(Cap_Structure->count_ch1)*div*Cap_Structure->clkfre/(float)REV_RCNT;	//Calculate channel 1 frequency

	
	DA1_DA0(Cap_Structure);

//	Cap_Structure->cap = Cref * (Cap_Structure->fre_ch1/Cap_Structure->fre_ch0*Cap_Structure->coef)  - Cp;
	
}

/***********************************************************************************************************************
  * @brief  Collect temperature information
  * @note   none
  * @param  Cap_Structure:CAP AFE information
  * @param  times:Average times
  * @retval none
  *********************************************************************************************************************/
void GetVT(CAP_AFE* Cap_Structure, u16 times)
{
	uint16_t adc_err=0;
  u32 adc_count=0,val1=0,val=0;
	u8 cfg;
	float Vref=0,Vin=0;
	
	uint16_t CalibrationData = *(uint16_t *)(0x1FFFF7E0);	//Get ADC calibration coefficients
	float  VrefCalculation = (float)CalibrationData * (float)3.3 / (float)4095.0;	
	
  CAP_AFE_Transmit(I2C_ADDR,RCNT_MSB,0xff);	
	CAP_AFE_Transmit(I2C_ADDR,RCNT_LSB,0xff);//Extend measurement time
	
	USART_Cmd(USART1, DISABLE);
	GPIOA->AFRL |=(uint32_t)0xf<<28;	
	MCO_PIN_OUT(0);	//Turn off external clock
	
	GPIOA->AFRL &=~(0xf<<12);
	GPIOA->CRL &=~(0xf<<12);  
	GPIOA->CRL |=0x03<<12; 		
	GPIOA->BRR |= GPIO_Pin_3;	// Pull down the Rx pin to prevent overcurrent
	
	CAP_AFE_Receive(I2C_ADDR,CFG,&cfg);	
	cfg &=~(0x03) ;
	cfg |=OS_SD_Single_Trans;	
	CAP_AFE_Transmit(I2C_ADDR,CFG,cfg);//Enable CAP AFE measurement
	ADC_Cmd(ADC1, ENABLE);	//Enable ADC measurement
	for(adc_count=0;adc_count<times;adc_count++)	
	{
		ADC1->CHANY0 &= ~(0XF<<0);	
		ADC1->CHANY0 |= 8<<0;
		ADC1->ADCR |= ADC_ADCR_ADST;
		while (RESET == ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
		ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
		val1 = ADC1 ->ADDR8&0xfff;	//Get external reference voltage
		Vref+=(float)4095.0 * (float)VrefCalculation / (float)val1;
		
		ADC1->CHANY0 &= ~(0XF<<0);
		ADC1->CHANY0 |= Cap_Structure->VT_CH.vt_ch<<0;
		ADC1->ADCR |= ADC_ADCR_ADST;
		while (RESET == ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
		ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
		val += ADC1 ->ADDATA&0xfff;	//Get VT voltage
	}
	Vin =val/4095.0*Vref/adc_count; 
	Cap_Structure->VDD = Vref/adc_count;
	ADC_Cmd(ADC1, DISABLE); 
	cfg &=~(0x03) ;
	cfg |=OS_SD_Stop_Trans;
	CAP_AFE_Transmit(I2C_ADDR,CFG,cfg);	
	Delay_ms(20);
	CAP_AFE_Transmit(I2C_ADDR,RCNT_MSB,0x5c);
	CAP_AFE_Transmit(I2C_ADDR,RCNT_LSB,0xd0);	//Restore measurement time
	
	GPIOA->AFRL &=~((uint32_t)0xf<<28|(uint32_t)0xf<<12);	
	GPIOA->AFRL |=0x3<<28;	//af3
	GPIOA->CRL &=~((uint32_t)0xf<<28|(uint32_t)0x08<<12);  
	GPIOA->CRL |=(uint32_t)0x09<<28|(uint32_t)0x08<<12; 	
	GPIOA->AFRL &=~(0xf<<12);
	GPIOA->AFRL |=0x1<<12;	//af1	
	GPIOA->BSRR |= GPIO_Pin_3;	//Configure Rx pins
	
	USART_Cmd(USART1, ENABLE);
	
	
	if(Cap_Structure->VT==0)Cap_Structure->VT=Vin/(times-adc_err);
	else Cap_Structure->VT=Cap_Structure->VT*0.4+Vin/(times-adc_err)*0.6;	//VT filter	
}

/********************************************IIC***************************************************
	*
	*
*******************************************************************************************************/\





/* Support size=0 for dummy write */

/**-----------------------------------------------------------------------
  * @brief  The host sends a start command to the chip
  * @param  None
  * @retval Flag bit
-------------------------------------------------------------------------*/
int I2C_Start(void)
{
	i2c_set_sda();
	i2c_set_scl();
	
	MY_DELAY_US(1);
	/*Bus free time(between Stop to Start time) tBUF>1.3us met by implement in stop() function*/
	i2c_clear_sda();
	MY_DELAY_US(1); 
	i2c_clear_scl();
	return GPIOI2C_BUS_BUSY;
}

/**-----------------------------------------------------------------------
  * @brief  The host sends a restart command to the chip
  * @param  None
  * @retval Flag bit
-------------------------------------------------------------------------*/
int I2C_reStart(void)
{
  /*ReStart condition */
	i2c_set_sda();
	MY_DELAY_US(1);  
	i2c_set_scl();
	MY_DELAY_US(1);  
	i2c_clear_sda();
	MY_DELAY_US(1); 
	i2c_clear_scl();
	MY_DELAY_US(1); 
	return GPIOI2C_BUS_BUSY;
}

/**-----------------------------------------------------------------------
  * @brief  The host sends a stop command to the chip
   * @param  None
  * @retval Flag bit
-------------------------------------------------------------------------*/
int I2C_Stop(void)
{
  /*Stop condition */
	i2c_clear_sda();
	MY_DELAY_US(1);  /*SU;STA*/
	i2c_set_scl();
	MY_DELAY_US(1);   /*tSU;STO*/
	i2c_set_sda();	
	MY_DELAY_US(1);/*tBUF>1.3us for Bus free time*/
	
	return GPIOI2C_BUS_IDLE;
}

/**-----------------------------------------------------------------------
  * @brief  The host sends a byte to the chip
  * @param  Bytes
  * @retval Whether to respond
-------------------------------------------------------------------------*/
int I2C_master_write(uint8_t b)
{
	uint8_t mask = 0x80, ack;
	do
	{	
		MY_DELAY_US(1);  /*tHD;DAT*/				
		sda_wr_control(b);	
		MY_DELAY_US(1);  /*tSU_DAT*/	
		i2c_set_scl();
		MY_DELAY_US(1);  /*nHigh*/
		i2c_clear_scl();			
	}while ((mask>>=1) != 0);

	/* ACK slot checking */
	MY_DELAY_US(1); /*tHD;DAT*/		
	i2c_set_sda();/* Release SDA, waiting for tVD_ACK */
	MY_DELAY_US(1);  /*tSU_DAT*/
	i2c_set_scl();
	MY_DELAY_US(1); /*tHD;DAT*/		
	ack = (i2c_get_sda()? 0:1);	
	MY_DELAY_US(1);  /*nHigh*/
	i2c_clear_scl();
	return (ack);
}

/**-----------------------------------------------------------------------
  * @brief  The host reads a byte from the chip
  * @param  ack:Response or non response to be sent to the chip
  * @retval One byte of data read
-------------------------------------------------------------------------*/
uint8_t I2C_master_read(uint8_t ack)
{ 
	uint8_t mask = 0x80, b = 0;

	i2c_set_sda();									/*Release SDA*/

	do
	{
		MY_DELAY_US(1);	
		i2c_set_scl();
		MY_DELAY_US(1);
		sda_rd_control(b);
		i2c_clear_scl();
		MY_DELAY_US(1);
	}while ((mask>>=1) != 0);

	/* ACK slot control */
	if(ack != 0) 
	{
		i2c_clear_sda();		/* SDA=0 for ACK*/
	}
	else
	{
		i2c_set_sda();		/* SDA=1 for NACK*/
	}	
	MY_DELAY_US(1);
	i2c_set_scl();
	MY_DELAY_US(1);
	i2c_clear_scl();
	MY_DELAY_US(1);

	return (b);
}

/**-----------------------------------------------------------------------
  * @brief  MC1122 no parameter instruction transfer function (for sending only instructions, such as temperature measurement and capacitance conversion)
  * @param  DeviceAddr  address  *Buff  Data storage array  Size  Total length of data sent
  * @retval Whether the transmission was successful
-------------------------------------------------------------------------*/
uint8_t CAP_AFE_Transmit(uint8_t DeviceAddr, uint8_t reg, uint8_t Data)
{
	uint8_t ret=GPIOI2C_XFER_LASTACK;
	
	if(I2C_Start()==GPIOI2C_BUS_ERROR)
	{
		I2C_Stop();
		return GPIOI2C_XFER_BUSERR; 
	}		

	if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ADDRNACK;
	}

	if(I2C_master_write(reg)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;	
	}

	if(I2C_master_write(Data)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;	
	}	

	I2C_Stop();
	return ret;	
}

/* Application assure size>=1. */
/**-----------------------------------------------------------------------
  * @brief  Data receiving function
  * @param  DeviceAddr  address  *Buff  Data storage array  Size  Total length of data sent
  * @retval Whether the transmission was successful
-------------------------------------------------------------------------*/
uint8_t CAP_AFE_Receive(uint8_t DeviceAddr, uint8_t reg,uint8_t *pData)
{
//	uint8_t i;
	
	if(I2C_Start()==GPIOI2C_BUS_ERROR)
  {
		
		I2C_Stop();
		return GPIOI2C_XFER_BUSERR; 
	}		
	
  if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
	{
//		PR("wraddress %x no ack\n",reg);
		I2C_Stop();
		return GPIOI2C_XFER_ADDRNACK;
	}
	
	if(I2C_master_write(reg)==GPIOI2C_NACK)
	{
//		PR("wrreg %x no ack\n",reg);
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;	
	}
	
	I2C_reStart();
	
  if(I2C_master_write((DeviceAddr<<1) | I2CREAD_MASK)== GPIOI2C_NACK)
	{
//		PR("raddress %x no ack\n",reg);
		I2C_Stop();

		return GPIOI2C_XFER_ABORTNACK;
	}	

	(*pData)=I2C_master_read(GPIOI2C_NACK);
	
	I2C_Stop();

	return GPIOI2C_XFER_LASTNACK;
}



